<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<script>
    /*
    * replace
    *   replace(str,subStr,newStr)
    *       str 原始字符串
    *       subStr 被替换字符串
    *       newStr 替换字符串
    *   思考一个问题：字符串永远没有办法修改，不如重新拼接生成一个字符串
    *   返回新的字符串
    *
    *
    * */
    function indexOfByYinShi(str,subStr,start = 0){
        str += ""
        subStr += "" //处理边界问题 如果不是字符串可以转成字符串
        //先弄清楚 i 表示什么
        //从头到尾进行比较，i 表示比较次数
        //i 还表示被比较的元字符串str 比较位置开始的下标 如 let str="abcdef"  let subStr="cd"
        //第一次比较，"cd"与"abcdef"中的"ab"比较，其中a的下标为0。第二次比较，"cd"与"abcdef"中的"bc"比较，其中b的下标为1，以此类推
        //还要弄清楚循环次数是多少 假如原字符串str长度为6，子字符串长度为6，只需要比较1次，原字符串长度为6，子字符串长度为5，需要比较2次，
        //原字符串长度为6，子字符串长度为4，需要比较3次...所以可以得出，比较次数为 i = str - subStr + 1 次，且可以先用变量来储存
        let length = str.length - subStr.length + 1
        let subLength = subStr.length
        //let flag = false //先假设找不到相同的
        for(let i = start;i < length;i++){
            let result = true //这个result表示单次外循环每一次每一组比较结果，可以先假设结果为正确
            //比较是两者之间的比较，刚刚只是分析了被比较的原字符串的情况，还有比较者子字符串的情况，也需要用一个循环来表示
            //又要弄清楚这次的 j 表示什么 我们要拿到子字符串比较的每一位的情况 可以用j表示被比较的每一位的下标
            //j的循环次数是多少，还是刚刚的情况，当我们拿到了原字符串"abcdef"中的"ab"与子字符串"cd"进行比较
            //要比较"ab"的不同"cd"，1次比较a与c相不相同，又1次b与d相不相同。然后"cd"又和下一组拿到的被比较的字符串"bc"进行比较
            //1次比较b与c相不相同，又1次比较c与d相不相同，由此可见，这次的循环比较次数 j = 子字符串的长度 也可以先用变量存储起来
            for(j = 0;j < subLength;j++) {
                if (subStr[j] !== str[i + j]) {//为什么是原字符串i+j 因为每次比较的子字符串每一位下标是固定的 而被比较的部分原字符串每一位下标是会依次递增的！
                    //一旦没找到，将result标记为失败，直接可以结束循环
                    result = false
                    break //跳出内层循环 返回外层循环继续比较下一组
                }
            }
            if(result){
                //找到匹配的元素了，将其下标返回出来
                return i
            }
        }
        return -1
    }



    //思路：最重要的是要知道替换字符串分为哪几个步骤，先将原字符串分为：前一部分 被替换部分 后一部分；前后两部分不用更改，直接中间拼接上新的一部分，就成功替换了
    //那么如何找出要被替换的那一部分 用之前的封装的indexOf方法 找到被替换部分的开始下标和结束位置
    function replaceByYinShi(str,subStr,newStr,start = 0){//原字符串，被替换部分，需要拼接的新部分，start表示从哪一位开始查询匹配，默认从0位开始
        //用一个变量表示被替换的字符串的开始下标位置
        let index = indexOfByYinShi(str,subStr,start)//传入参数：原字符串，被替换部分，start表示从哪一位开始查询；返回被替换部分的开始下标
        //如果没查到被替换字符串 那下标就为-1 就返回原字符串
        if(index === -1){
            return str
        }
        //如果查到了，生成新的字符串，新的拼接字符串包括 原先字符串的前一部分 + 需要替换的新部分 + 原先字符串的后一部分
        //表示前一部分
        let left = ""

        //表示后一部分
        let right = ""

        //将left和right生成出来
        //用一个循环表示生成前一部分
        for (let i = 0;i < index;i++){//前一部分下标从0开始，一直遍历到被替换部分的开始下标位置，所以i小于index
            left += str[i] //再将每次从原字符串中遍历到的下标所代表的字符拼接赋值给前一部分 这样就生成了前一部分
        }
        //再像刚才一样用一个循环生成后一部分
        for(let i = index + subStr.length;i < str.length;i++){//后一部分的下标从被替换字符串的结束位置开始 就是
            //被替换字符串下标开始的地方加上被替换字符串的长度 然后一直遍历到原字符串最后一位 在这之间被遍历到的字符串就是后一部分的内容
            right += str[i] //再将每次从原字符串中遍历到的下标所代表的字符拼接赋值给后一部分 这样就生成了后一部分
        }

        return left + newStr + right
    }

    console.log(replaceByYinShi("abcdef","d","3"))


    /*
    * replaceAll的方法
    *   就是replace方法的升级版 多次进行replace 最终生成新的字符串
    *   接收参数：str subStr newStr
    *   返回一个新字符串
    *
    * */
    //思路：首先需要查询到需要被替换的部分字符串的开始下标，从该位置进行替换，生成新的被替换之后的字符串；
    //再从刚刚被替换的结束位置再开始查询，再找到需要被替换的部分字符串的开始下标，从该位置进行替换，再次生成新的被替换之后的字符串；
    //再次重复以上操作，直到所有需要被替换部分都替换完成之后，输出最终生成的新字符串
    function replaceAllByYinShi(str,subStr,newStr){
        //用一个变量start 表示被替换部分的开始下标
        let start = 0
        while(indexOfByYinShi(str,subStr,start) > -1){//如果每次都能查询到需要被替换的部分的下标就执行下面代码
            //index表示每次找到的需要被替换部分的位置下标；
            let index = indexOfByYinShi(str,subStr,start)//start表示每次找下标的时候从新的start所代表的下标开始找
            //str表示每次被替换之后的新生成的字符串
            str = replaceByYinShi(str,subStr,newStr,index)//index表示告诉原字符串在index所表示的下标去替换 需要被替换的 部分字符串
            //再将查询的开始位置下标strat更新 用之前查到的替换开始下标 + 用来替换的新字符串的长度 赋值给新的start 再循环进行新一轮查询替换
            start = index + newStr.length
        }
        return str //直到循环到没有需要被替换的部分之后 将最终的新生成的字符串返回出来
    }

    console.log(replaceAllByYinShi("你好，我好，大家好", "好", "很好"));
    //第一次找到"你好，我好，大家好"中的第一个"好"的下标，替换成"很好"，生成新的字符串"你很好，我好，大家好"
    //再从刚刚找到并替换之后的"你很好"的下标作为新的开始位置，找到下一个"好"的下标，替换生成"你很好，我很好，大家好"
    //再次重复以上操作直至结束


</script>
</body>
</html>